package com.theeviljames.linearAlgebra;

import com.theeviljames.base.IMatrixOps;
import com.theeviljames.base.MatrixOps;

public class GaussJordan {

	private static IMatrixOps m = MatrixOps.getMatrixOps();

	/**
	 * Only works on square matrices
	 * @param matrix
	 * @return
	 */
	public static double[][] getInverse(double[][] matrix){
		System.out.println("Original Matrix");
		m.print(matrix);
		matrix = m.append(matrix,m.getIdentityMatrix(matrix.length));
		int n = matrix.length;
		//Does the top down elimination
		System.out.println("Top down elimination");
		for(int i = 0; i < n-1; i++){
			double[][] e = m.getIdentityMatrix(n);
			e[i+1][i] = -(matrix[i+1][i]/matrix[i][i]);
			System.out.println("Elimination Matrix " + i + ">");
			m.print(e);
			matrix = m.times(e, matrix);
		}
		m.print(matrix);
		//Does the bottom up elimination
		System.out.println("Bottom up elimination");
		for(int i = 0; i < n-1; i++){
			double[][] e = m.getIdentityMatrix(n);
			e[i][i+1] = -(matrix[i][i+1]/matrix[i+1][i+1]);
			System.out.println("Elimination Matrix " + i + ">");
			m.print(e);
			matrix = m.times(e, matrix);
		}
		m.print(matrix);
		//If necessary divides rows by correct amounts to give the identity matrix on the LHS
		for(int i = 0; i < n; i++){
			if(matrix[i][i]!=1.0){
				matrix = m.scalarDivideRow(matrix,i,matrix[i][i]);
			}
		}
		
		double[][] result = new double[n][n];
		result = m.extract(matrix,1,n+1,n,n*2);
		return result;
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//double[][] test = new double[][]{{1,3},{2,7}};
		double[][] test = new double[][]{{3,2},{6,9}};
		double[][] t = getInverse(test);
		System.out.println("Straight outta main(String args[])");
		m.print(t);
		
		double[][] ident = m.times(test,t);
		System.out.println("This should be the indentity matrix");
		m.print(ident);
	}

}
